In [1]:
# This line configures matplotlib to show figures embedded in the notebook,
# instead of opening a new window for each figure. More about that later.
# If you are using an old version of IPython, try using '%pylab inline' instead.
%matplotlib inline
from pysolve.model import Model
from pysolve.utils import is_close,round_solution
import matplotlib.pyplot as plt
In [2]:
def create_insoutb_model():
model = Model()
model.set_var_default(0)
model.var('Ad', desc='Demand for Central bank advances from commercial banks')
model.var('As', desc='Supply of central bank advances to commercial banks')
model.var('Bbd', desc='Government bills demanded by commercial banks')
model.var('Bbdn', desc='Notional demand for government bills from commercial banks')
model.var('Bcb', desc='Government bills held by Central bank')
model.var('Bhd', desc='Demand for government bills')
model.var('Bhh', desc='Government bills held by households')
model.var('Bs', desc='Supply of government bills')
model.var('BLd', desc='Demand for government bonds')
model.var('BLh', desc='Demand for government bonds')
model.var('BLs', desc='Supply of government bonds')
model.var('BLR', desc='Gross bank liquidity ratio')
model.var('BLRn', desc='Net bank liquidity ratio')
model.var('BPM', desc="Banks' profit margin")
model.var('Ck', desc='Real consumption')
model.var('CG', desc='Capital gains on government bonds')
model.var('CONS', desc='Consumption at current prices')
model.var('F', desc='Realized profits of firms and banks')
model.var('Fb', desc='Realized profits of firms and banks')
model.var('Fcb', desc='Central bank "profits"')
model.var('Ff', desc='Realized firm profits')
model.var('Ffe', desc='Expected profits of firms')
model.var('G', desc='Government expenditures')
model.var('Hbd', desc='Cash required by banks')
model.var('Hbs', desc='Cash supplied to banks')
model.var('Hhd', desc='Household demand for cash')
model.var('Hhh', desc='Cash held by households')
model.var('Hhs', desc='Cash supplied by households')
model.var('Hs', desc='Total supply of cash')
model.var('IN', desc='Stock of inventories at current costs')
model.var('INk', desc='Real inventories')
model.var('INke', desc='Expected real inventories')
model.var('INkt', desc='Target level of real inventories')
model.var('Ld', desc='Demand for loans')
model.var('Ls', desc='Supply of loans')
model.var('M1h', desc='Checking deposits held by households')
model.var('M1hn', desc='Notional holding of checking deposits')
model.var('M1s', desc='Checking deposits supplied by banks')
model.var('M2d', desc='Demand for term deposits - constrained to be non-negative')
model.var('M2h', desc='Term deposits held by households')
model.var('M2s', desc='Term deposits supplied by banks')
model.var('N', desc='Employment level')
model.var('NHUC', desc='Normal historic unit costs')
model.var('omegat', desc='Target real wage for workers')
model.var('P', desc='Price level')
model.var('Pbl', desc='Price of government bonds')
model.var('PI', desc='Price inflation')
model.var('PSBR', desc='Government deficit')
model.var('Ra', desc='Interest rate on Central bank advances')
model.var('Rb', desc='Interest rate on government bills')
model.var('Rbl', desc='Interest rate on bonds')
model.var('Rl', desc='Interest rate on loans')
model.var('Rm', desc='Interest rate on deposits')
model.var('RRb', desc='Real interest rate on bills')
model.var('RRbl', desc='Real interest rate on long term bonds')
model.var('RRl', desc='Real interest rate on loans')
model.var('RRm', desc='Real interest rate on term deposits')
model.var('S', desc='Sales at current prices')
model.var('Sk', desc='Real sales')
model.var('Ske', desc='Expected real sales')
model.var('sigmas', desc='Realized inventories to sales ratio')
model.var('sigmat', desc='Target inventories to sales ratio')
model.var('T', desc='Taxes')
model.var('UC', desc='Unit costs')
model.var('V', desc='Wealth of households')
model.var('Ve', desc='Expected household wealth')
model.var('Vk', desc='Real wealth of households')
model.var('Vnc', desc='Wealth of households, net cash')
model.var('Vnce', desc='Expected wealth of households, net cash')
model.var('WB', desc='The wage bill')
model.var('Y', desc='Output at current prices')
model.var('Yk', desc='Real output')
model.var('YDhs', desc='Haig-Simons measure of disposable income')
model.var('YDkhs', desc='Haig-Simons measure of real disposable income')
model.var('YDkr', desc='Regular real disposable income')
model.var('YDkre', desc='Expected regular real disposable income')
model.var('YDr', desc='Regular disposable income')
model.var('YDre', desc='Expected regular disposable income')
model.set_param_default(0)
model.param('alpha0', desc='Autonomous consumption')
model.param('alpha1', desc='Propensity to consume out of income')
model.param('alpha2', desc='Propensity to consume out of wealth')
model.param('beta', desc='Parameter in expectation formations on real sales')
model.param('bot', desc='Bottom value for bank net liquidity ratio')
model.param('botpm', desc='Bottom value for bank profit margin')
model.param('eps', desc='Parameter in expectation formations on real disposable income')
model.param('gamma', desc='Speed of adjustment of inventories to the target level')
model.param('lambda20', desc='Parameter in household demand for time deposits')
model.param('lambda21', desc='Parameter in household demand for time deposits')
model.param('lambda22', desc='Parameter in household demand for time deposits')
model.param('lambda23', desc='Parameter in household demand for time deposits')
model.param('lambda24', desc='Parameter in household demand for time deposits')
model.param('lambda25', desc='Parameter in household demand for time deposits')
model.param('lambda30', desc='Parameter in household demand for bills')
model.param('lambda31', desc='Parameter in household demand for bills')
model.param('lambda32', desc='Parameter in household demand for bills')
model.param('lambda33', desc='Parameter in household demand for bills')
model.param('lambda34', desc='Parameter in household demand for bills')
model.param('lambda35', desc='Parameter in household demand for bills')
model.param('lambda40', desc='Parameter in household demand for bonds')
model.param('lambda41', desc='Parameter in household demand for bonds')
model.param('lambda42', desc='Parameter in household demand for bonds')
model.param('lambda43', desc='Parameter in household demand for bonds')
model.param('lambda44', desc='Parameter in household demand for bonds')
model.param('lambda45', desc='Parameter in household demand for bonds')
model.param('lambdac', desc='Parameter in household demand for cash')
model.param('phi', desc='Mark-up on unit costs')
model.param('ro1', desc='Reserve requirements parameter')
model.param('ro2', desc='Reserve requirements parameter')
model.param('sigma0', desc='Parameter determining the target inventories to sales ratio')
model.param('sigma1', desc='Parameter linking the target inventories to sales ratio to the interest rate')
model.param('tau', desc='Sales tax rate')
model.param('top', desc='Top value for bank net liquidity ratio')
model.param('toppm', desc='Top value for bank profit margin')
model.var('z1', desc='Is 1 if bank checking accounts are non-negative')
model.var('z2', desc='Is 1 if bank checking accounts are negative')
model.var('z3', desc='Is 1 if banks net liquidity ratio is below bottom level')
model.var('z4', desc='Is 1 if banks net liquidity ratio was below bottom level')
model.var('z4b', desc='Is 1 if banks net liquidity ratio was way below bottom level')
model.var('z5', desc='Is 1 if banks net liquidity ratio was above top level')
model.var('z5b', desc='Is 1 if banks net liquidity ratio was way above top level')
model.var('z6', desc='Is 1 if banks profit margin is below bottom level')
model.var('z7', desc='Is 1 if banks profit margin is above top level')
model.param('xib', desc='Parameter in the equation for setting interest rate on deposits')
model.param('xil', desc='Parameter in the equation for setting interest rate on loans')
model.param('xim', desc='Parameter in the equation for setting interest rate on deposits')
model.param('omega0', desc='Parameter influencing the target real wage for workers')
model.param('omega1', desc='Parameter influencing the target real wage for workers')
model.param('omega2', desc='Parameter influencing the target real wage for workers')
model.param('omega3', desc='Speed of adjustment of wages to target value')
model.param('ERrbl', desc='Expected rate of return on long term bonds')
model.param('Gk', desc='Real government expenditures')
model.param('Nfe', desc='Full employment level')
model.param('PR', desc='Labour productivity')
model.param('Rbbar', desc='Interest rate on bills, set exogenously')
model.param('Rblbar', desc='Interest rate on bonds, set exogenously')
model.var('W', desc='Wage rate')
# Box 10.1 Firms' decisions
# -------------------------
model.add('Yk = Ske + INke - INk(-1)') # 10.1 : Real output
model.add('N = Yk/PR') # 10.2 : Employment
model.add('WB = N*W') # 10.3 : The wage bill
model.add('UC = WB/Yk') # 10.4 : Unit costs
model.add('Ske = beta*Sk(-1) + (1-beta)*Ske(-1)') # 10.5 : Expected real sales
model.add('INkt = sigmat * Ske') # 10.6 : Target level of real inventories
model.add('sigmat = sigma0 - sigma1*Rl') # 10.7 : Target inventories to sales ratio
model.add('RRl = (1 + Rl)/(1 + PI) - 1') # 10.8 : Real interest rate on loans
model.add('INke = INk(-1) + gamma*(INkt - INk(-1))') # 10.9 : Expected real inventories
model.add('NHUC = (1 - sigmat)*UC + sigmat*(1 + Rl(-1))*UC(-1)') # 10.11 : Normal historic unit costs
model.add('P = (1 + tau)*(1 + phi)*NHUC') # 10.10 : Price level
model.add('Ffe = (phi/(1+phi))*(1/(1+tau))*P*Ske') # 10.11A : Expected profits of firms
# Box 10.2 : Firms' equations
# ---------------------------
model.add('Sk = Ck + Gk') # 10.12 : Real sales
model.add('S = P * Sk') # 10.13 : Sales at current prices
model.add('INk - INk(-1) = Yk - Sk') # 10.14 : Real inventories
model.add('sigmas = INk(-1)/Sk') # 10.15 : Realized inventories to sales ratio
model.add('IN = INk*UC') # 10.16 : Stock of inventories
model.add('Ld = IN') # 10.17 : Demand for loans
model.add('Ff = S - T - WB + IN - IN(-1) - Rl(-1)*IN(-1)') # 10.18 : Firms realized profits
model.add('PI = P/P(-1) - 1') # 10.19 : Rate of price inflation
# Box 10.3 : Household equations
# ------------------------------
model.add('YDr = WB + F + Rm(-1)*M2d(-1) + Rb(-1)*Bhh(-1) + BLh(-1)') # 10.20 : Regular disposable income
model.add('CG = (Pbl - Pbl(-1))*BLh(-1)') # 10.21 : Capital gains on bonds
model.add('YDhs = YDr + CG') # 10.22 : Haig-Simons measure of disposable income
model.add('F = Ff + Fb') # 10.23 : Total net profits
model.add('V = V(-1) + YDhs - CONS') # 10.24 : Nominal wealth
model.add('Vnc = V - Hhd') # 10.25 : Nominal wealth net of cash
model.add('YDkr = (YDr - PI*V(-1))/P') # 10.26 : Real regular disposable income
model.add('YDkhs = (YDr - PI*V(-1) + CG)/P') # 10.27 : Real HS disposable income
model.add('Vk = V/P') # 10.28 : Real wealth of households
# Box 10.4 : Household equations
# ------------------------------
model.add('Ck = alpha0 + alpha1*YDkre + alpha2*Vk(-1)') # 10.29 : Consumption decision
model.add('YDkre = eps*YDkr(-1) + (1 - eps)*YDkre(-1)') # 10.30 : Expected real regular disposable income
model.add('CONS = Ck*P') # 10.31 : Consumption at current prices
model.add('YDre = P*YDkre + PI*V(-1)/P') # 10.32 : Expected regular disposable income
model.add('Ve = V(-1) + YDre - CONS') # 10.33 : Expected nominal wealth
model.add('Hhd = lambdac*CONS') # 10.34 : Household demand for cash
model.add('Vnce = Ve - Hhd') # 10.35 : Expected nominal wealth net of cash
# Box 10.5 : Households portfolio equations, based on nominal rates
# -----------------------------------------------------------------
# 10.37 : Demand for term banks deposit
model.add('M2d = (lambda20 + lambda22*Rm + lambda23*Rb + lambda24*ERrbl + lambda25*(YDre/Vnce))*Vnce')
# 10.38 : Demand for government bills
model.add('Bhd = (lambda30 + lambda32*Rm + lambda33*Rb + lambda34*ERrbl + lambda35*(YDre/Vnce))*Vnce')
# 10.39 : Demand for government bonds
model.add('BLd = (lambda40 + lambda42*Rm + lambda43*Rb + lambda44*ERrbl + lambda45*(YDre/Vnce))*Vnce/Pbl')
# Box 10.6 : Households portfoloio equations, based on real rates
# ---------------------------------------------------------------
# 10.37A : "Notional" Demand for term banks deposits
# M2d = (lambda20 - lambda21*PI/(1 + PI) + lambda22*RRm + lambda23*RRb + lambda24*RRbl + lambda25*YDre/Vnce))*Vnce
# 10.38A : Demand for government bills
# Bhd = (lambda30 - lambda31*PI/(1 + PI) + lambda32*RRm + lambda33*RRb + lambda34*RRbl + lambda35*YDre/Vnce))*Vnce
# 10.39A : Demand for government bonds
# BLd = (lambda40 - lambda41*PI/(1 + PI) + lambda42*RRm + lambda43*RRb + lambda44*RRbl + lambda45*YDre/Vnce))*Vnce/PIbl
model.add('RRm = (1 + Rm)/(1 + PI) - 1') # 10.37B : Real interest rate on term deposits
model.add('RRb = (1 + Rb)/(1+ PI) - 1') # 10.38B : Real interest rate on bills
model.add('RRbl = (1 + Rbl)/(1 + PI) - 1') # 10.39B : Real interest rate on long-term bonds
# Box 10.7 : Households equations, realized portfolio asset holding
# -----------------------------------------------------------------
model.add('Hhh = Hhd') # 10.40 : Cash holding
model.add('Bhh = Bhd') # 10.41 : Holding of bills
model.add('BLh = BLd') # 10.42 : Holding of bonds
model.add('M1hn = Vnc - M2d - Bhd - Pbl*BLd') # 10.43 : Notional holding of bank checking accounts
model.add('M1h = M1hn * z1') # 10.44 : Holding of bank checking accounts
model.add('z1 = if_true(M1hn >= 0)') # 10.45 : Condition for non-negative bank checking acounts
model.add('M2h = M2d*z1 + (Vnc - Bhh - Pbl*BLd)*z2') # 10.46 : Holding of bank term deposits
model.add('z2 = 1 - z1') # 10.47 : Condition for negative bank checking accounts
# Box 10.8 : Government equations
# -------------------------------
model.add('T = S*tau/(1 + tau)') # 10.48 : Tax receipts
model.add('G = P*Gk') # 10.49 : Government expenditures
model.add('PSBR = G + Rb(-1)*Bs(-1) + BLs(-1) - (T + Fcb)') # 10.50 : Government deficit
model.add('Bs - Bs(-1) = PSBR - (BLs - BLs(-1))*Pbl') # 10.51 : New issues of bills
model.add('BLs = BLd') # 10.52 : Supply of bonds
model.add('Pbl = 1/Rbl') # 10.53 : Price of bonds
model.add('Rbl = Rblbar + PI(-1)') # 10.54 : Yield on bonds is exogenous
# Box 10.9 : Central bank equations
# ---------------------------------
model.add('Hs = Bcb + As') # 10.55 : Supply of cash
model.add('Hbs = Hs - Hhs') # 10.56 : Supply of cash to commercial banks
model.add('Bcb = Bs - Bhh - Bbd') # 10.57 : CB purchases of government bills
model.add('Rb = Rbbar + PI(-1)') # 10.58 : Interest rate on government bills, set exogenously
model.add('As = Ad') # 10.59 : Supply of CB advances to commercial banks
model.add('Ra = Rb') # 10.60 : Interest rate on CB advances
model.add('Fcb = Rb(-1)*Bcb(-1) + Ra(-1)*As(-1)') # 10.61 : Profits of Central Bank
# Box 10.10 : Commercial bank equations
# -------------------------------------
model.add('Hhs = Hhd') # 10.62 : Supply of cash to households
model.add('M1s = M1h') # 10.63 : Supply of checking deposits
model.add('M2s = M2d') # 10.64 : Supply of time deposits
model.add('Ls = Ld') # 10.65 : Supply of loans
model.add('Hbd = ro1*M1s + ro2*M2s') # 10.66 : Demand for cash by banks (reserve requirement)
# Box 10.11 : Commercial bank equations
# -------------------------------------
model.add('Bbdn = M1s + M2s - Ls - Hbd') # 10.67 : Notional demand for bills
model.add('BLRn = Bbdn/(M1s + M2s)') # 10.68 : Net bank liquidity ratio
model.add('Ad = (bot*(M1s + M2s) - Bbdn)*z3') # 10.69 : Advances needed by banks
model.add('z3 = if_true(BLRn < bot)') # 10.70 : Check if net liquidity is above bottom value
model.add('Bbd = Ad + M1s + M2s - Ls - Hbd') # 10.71 : Demand for government bills
model.add('BLR = Bbd/(M1s + M2s)') # 10.72 : Gross bank liquidity ratio
# Box 10.12 : Commercial bank equations
# -------------------------------------
# 10.73 : Interest rate on deposits
model.add('Rm = Rm(-1) + 0.0001*z4 + 0.0002*z4b - 0.0001*z5 - 0.0002*z5b + xib*(Rb - Rb(-1))')
model.add('z4 = if_true(BLRn(-1) < bot)') # 10.75 : Check if net liquidity ratio was below bottom value
model.add('z4b = if_true(BLRn(-1) < (bot - 0.02))')
model.add('z5 = if_true(BLRn(-1) > top)') # 10.76 : Check if net liquidity ratio was above top value
model.add('z5b = if_true(BLRn(-1) > (top+0.02))')
# 10.77 : Realized bank profits
model.add('Fb = Rl(-1)*Ls(-1) + Rb(-1)*Bbd(-1) - Rm(-1)*M2s(-1) - Ra(-1)*Ad(-1)')
model.add('Rl - Rl(-1) = xil*(z6 - z7) + (Rb - Rb(-1))') # 10.78 : Interest rate on loans
model.add('z6 = if_true(BPM < botpm)') # 10.80 : Check if banks profit margin is below bottom value
model.add('z7 = if_true(BPM > toppm)') # 10.81 : Check if banks profit margin is above top value
model.add('BPM = (Fb + Fb(-1))/(M1s(-1) + M1s(-2) + M2s(-1) + M2s(-2))') # 10.82 : Banks profit margin
# Inflationary forces
# -------------------
# 10.84 : Target real wage for workers
model.add('omegat = exp(omega0 + omega1*log(PR) + omega2*log((N/Nfe)))')
model.add('W = W(-1)*(1 + omega3*(omegat(-1) - W(-1)/P(-1)))') # 10.85 Unit wages
# Addtional equations
# -------------------
model.add('Y = P*Sk + (INk - INk(-1))*UC') # Output at current prices
return model
insoutb_parameters = {'alpha0': 0,
'alpha1': 0.95,
'alpha2': 0.05,
'beta': 0.5,
'bot': 0.02,
'botpm': 0.002,
'eps': 0.5,
'gamma': 0.5,
'lambda20': 0.52245,
'lambda21': 20,
'lambda22': 40,
'lambda23': -20,
'lambda24': -20,
'lambda25': -0.06,
'lambda30': 0.47311,
'lambda31': 40,
'lambda32': -20,
'lambda33': 40,
'lambda34': -20,
'lambda35': -0.06,
'lambda40': 0.17515,
'lambda41': 20,
'lambda42': -20,
'lambda43': -20,
'lambda44': 40,
'lambda45': -0.06,
'lambdac': 0.1,
'phi': 0.1,
'ro1': 0.1,
'ro2': 0.1,
'sigma0': 0.3612,
'sigma1': 3,
'tau': 0.25,
'top': 0.04,
'toppm': 0.005,
'xib': 0.9,
'xil': 0.002,
'xim': 0.0002,
'omega0': -0.32549,
'omega1': 1,
'omega2': 1.5,
'omega3': 0.1}
insoutb_exogenous = {'Gk': 25,
'Nfe': 133.28,
'PR': 1,
'Rbbar': 0.023,
'Rblbar': 0.027,
'ERrbl': 0.027,
'W': 1}
insoutb_variables = [('Bbd', 1.19481),
('Bbdn', 1.19481),
('Bcb', 19.355),
('Bhh', 49.69136),
('Bhd', 'Bhh'),
('Bs', 70.24123),
('BLh', 1.12309),
('BLd', 'BLh'),
('BLs', 'BLd'),
('Hbd', 4.36249),
('Hbs', 'Hbd'),
('Hhd', 14.992),
('Hhh', 'Hhd'),
('Hhs', 'Hhd'),
('INk', 38.07),
('INke', 'INk'),
('IN', 38.0676),
('Ls', 38.0676),
('Ld', 'Ls'),
('M1s', 3.9482),
('M1h', 'M1s'),
('M1hn', 'M1s'),
('M2s', 39.667),
('M2d', 'M2s'),
('M2h', 'M2d'),
('Vk', 108.285),
('Ra', 0.02301),
('Rb', 0.02301),
('Rl', 0.02515),
('Rm', 0.02095),
('BLRn', 0.02737),
('Fb', 0.1535),
('P', 1.38469),
('Pbl', 37.06),
('Rbl', 'Rblbar'),
('Sk', 133.277),
('Ske', 'Sk'),
('UC', 1),
('YDkr', 108.28),
('YDkre', 108.28),
('V', 'Vk*P'),
('Ve' , 'V'),
('Vnc', 'V - Hhh'),
('Vnce', 'Vnc'),
('omegat', 0.72215)]
In [3]:
baseline = create_insoutb_model()
baseline.set_values(insoutb_parameters)
baseline.set_values(insoutb_exogenous)
baseline.set_values(insoutb_variables)
# run to convergence
# Give the system more time to reach a steady state
for _ in xrange(65):
baseline.solve(iterations=200, threshold=1e-6)
In [4]:
omega0 = create_insoutb_model()
omega0.set_values(insoutb_parameters)
omega0.set_values(insoutb_exogenous)
omega0.set_values(insoutb_variables)
for _ in xrange(15):
omega0.solve(iterations=200, threshold=1e-6)
omega0.set_values({'omega0': -0.28})
for _ in xrange(50):
omega0.solve(iterations=200, threshold=1e-6)
In [5]:
caption = '''
Figure 10.7A Evolution of real sales following a one-step increase in the target real wage
that generates an increase in the rate of inflation, accompanied by an increase in the
nominal interest rate the approximately compensates for the increase in inflation.'''
skdata = [s['Sk'] for s in omega0.solutions[5:]]
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off', right='off')
axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
axes.plot(skdata, linestyle='-', color='b')
# add labels
plt.text(20, 132.6, 'Real sales')
fig.text(0.1, -.1, caption);
In [6]:
caption = '''
Figure 10.7B Evolution of real household debt and real government debt following
a one-step increase in the target real wage that generates an increase in the
rate of inflation, accompanied by an increase in nominal interest rates that
approximately compensates for the increase in inflation.'''
wdata = [(s['Bs'] + s['BLs']*s['Pbl'])/s['P'] for s in omega0.solutions[5:]]
vkdata = [s['Vk'] for s in omega0.solutions[5:]]
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off', right='off')
axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
axes.set_ylim(65, 115)
axes.plot(vkdata, linestyle='-', color='g')
axes.plot(wdata, linestyle='-', color='b')
# add labels
plt.text(20, 82, 'Real government debt')
plt.text(20, 109, 'Real household wealth')
fig.text(0.1, -.15, caption);
In [7]:
caption = '''
Figure 10.7C Evolution of the deflated government baance, adjusted and
unadjusted for inflation gains, following a one-step increase in the target
real wage that generates an increase in the rate of inflation, accompanied
by an increase in nominal interest rates that approximately compenstates for
the increase in inflatio.'''
psbrdata = list()
data = list()
for i in xrange(5, len(omega0.solutions)):
s7 = omega0.solutions[i]
s7_1 = omega0.solutions[i-1]
s0 = baseline.solutions[i]
s0_1 = baseline.solutions[i-1]
psbrdata.append((s0['PSBR']/s0['P']) - (s7['PSBR']/s7['P']))
data.append((-s7['PSBR'] + (s7['P'] - s7_1['P'])*(s7_1['Bs']+s7_1['BLs']*s7_1['Pbl'])/s7['P']) -
(-s0['PSBR'] + (s0['P'] - s0_1['P'])*(s0_1['Bs']+s0_1['BLs']*s0_1['Pbl'])/s0['P']))
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off', right='off')
axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
#axes.set_ylim(-0.5, 1)
axes.plot(psbrdata, color='b')
axes.plot(data, linestyle='-', color='g')
# add labels
plt.text(17, 0.2, 'Real government budget balance')
plt.text(17, 0.17, '(adjusted for inflation gains)')
plt.text(21, -0.19, 'Real government budget balance')
plt.text(21, -0.22, '(unadjusted for inflation gains)')
fig.text(0.1, -.2, caption);
In [ ]: